/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package deatax.display.miniboard;

import deatax.GameData;
import deatax.Player;
import deatax.Tile;
import deatax.card.Card;
import deatax.display.DefaultTileRenderer;
import deatax.display.ProximityGroup;
import deatax.display.TileRenderer;
import java.util.ArrayList;
import javax.media.opengl.GL2;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;

/**
 *
 * @author nrechten
 */
public class MiniBoard {

    ArrayList<MiniBoardTile> tiles;
    //int[] path;
    public static float[] hex = DefaultTileRenderer.genHex(1);
    public static float th = 1;
    public static float tw = 1;
    public static float tgx = 1;
    protected ProximityGroup pg = new ProximityGroup();
    protected ArrayList<MiniMarker> markers;
    protected GameData data;
    protected DiceRenderer dice;
    protected DiceBowl bowl;
    protected float width = 10;
    protected float height = 10;
    float position = 0;
    public static float RESIZE_SPEED = 0.05f;
    public static int SMALL_WIDTH = 300;
    public static int SMALL_HEIGHT = 200;
    public Tile background;
    
    public CardRenderer card;
    
    public ArrayList<MiniBoardTile> specialTiles = new ArrayList<MiniBoardTile>();

    public MiniBoard(/*int[] path, */GameData gd) {
        th = hex[3];
        tw = hex[0];
        tgx = tw * 2 - tw / 2;
        //this.path = path;

        markers = new ArrayList<MiniMarker>();
        tiles = new ArrayList<MiniBoardTile>();

        background = new Tile();

        width = tgx * 6 / 2;
        height = th * 4 / 2;

        data = gd;
        bowl = new DiceBowl(3,1,data,this);
        
        specialTiles.add(new CardStackRenderer(2,1,"Death",this));
        specialTiles.add(new CardStackRenderer(4,1,"Tax",this));
        specialTiles.add(bowl);
        
    }

    public void removeMarker(Player p) {
        MiniMarker r = null;
        for (MiniMarker m : markers) {
            if (m.player == p) {
                r = m;
                break;
            }
        }
        if (r != null) {
            markers.remove(r);
        }
    }

    public void addTile(MiniBoardTile mbt) {
        tiles.add(mbt);
    }

    public MiniBoardTile getTile(int pos) {
        return tiles.get(pos);
    }

    public void init() {
        for (Player player : data.getRoster().getPlayers()) {
            MiniMarker mm = new MiniMarker(player, this);
            mm.addRevolutionListener(data.getMode());
            mm.addRevolutionListener(player);
            markers.add(mm);
            mm.setTile(getTile(0));
            getTile(0).addMarker(mm);
        }
    }

    public boolean maximise() {
        if (position == 1) {
            return true;
        }
        position += RESIZE_SPEED;
        if (position >= 1) {
            position = 1;
            return true;
        }
        return false;
    }

    public boolean minimise() {
        if (position == 0) {
            return true;
        }
        position -= RESIZE_SPEED;
        if (position <= 0) {
            position = 0;
            return true;
        }
        return false;
    }

    public MiniMarker getMarker(Player p) {
        for (MiniMarker m : markers) {
            if (m.player == p) {
                return m;
            }
        }
        return null;
    }

    public void draw(GL2 gl, GLU glu) {


        int[] viewport = new int[4];
        gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);

        if (position == 0) {
            gl.glViewport(viewport[2] - SMALL_WIDTH, 0, SMALL_WIDTH, SMALL_HEIGHT);
        } else {
            float ipos = 1 - position;
            if (viewport[2] < viewport[3]) {
                gl.glViewport(
                        Math.round((viewport[2] - SMALL_WIDTH) * ipos),
                        Math.round(((viewport[3] - (SMALL_HEIGHT / (float) SMALL_WIDTH) * viewport[2]) / 2) * position),
                        Math.round(SMALL_WIDTH * ipos + viewport[2] * position),
                        Math.round(SMALL_HEIGHT * ipos + ((SMALL_HEIGHT / (float) SMALL_WIDTH) * viewport[2]) * position));
            } else {
                gl.glViewport(
                        Math.round((viewport[2] - SMALL_WIDTH) * ipos) - Math.round(((viewport[2] / 2 - (SMALL_WIDTH / (float) SMALL_HEIGHT) * viewport[3]) / 2) * position),
                        0,
                        Math.round(SMALL_WIDTH * ipos + ((SMALL_WIDTH / (float) SMALL_HEIGHT) * viewport[3]) * position),
                        Math.round(SMALL_HEIGHT * ipos + viewport[3] * position));
            }
        }


        gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
        gl.glLoadIdentity();    // reset
        glu.gluPerspective(45.0f, 1, 0.1f, 500.0f);

        gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
        gl.glLoadIdentity();

        gl.glDisable(GL2.GL_DEPTH_BUFFER);
        gl.glDisable(GL2.GL_BLEND);
//        glu.gluLookAt(4.5f, 0, 10, 4.5f, 5, -15, 0, 1, 0);
        glu.gluLookAt(0, -9.5f, 8.5f, 0, 0, 0, 0, 1, 0);
//        glu.gluLookAt(0, 0, 8.5f, 0, 0, 0, 0, 1, 0);

        TileRenderer renderer = data.getRender().default_renderer;
//      System.out.println(renderer.getClass().getName() +  ":" + selected.getTerrain().getName());
        renderer.draw(gl, background, 0, 0, 0, 0);


        float scale = 0.2f;
        gl.glScalef(scale, scale, scale);
        scale = 1 / scale;
        for (MiniBoardTile mbt : tiles) {
            float[] xy = mapToGrid(mbt.x + 1, mbt.y);
            gl.glTranslatef(xy[0] * scale, xy[1] * scale, 1.2f);
            mbt.draw(gl);
            gl.glTranslatef(-xy[0] * scale, -xy[1] * scale, -1.2f);
        }
        for (MiniBoardTile csr : specialTiles) {
            float[] xy = mapToGrid(csr.x, csr.y);
            gl.glTranslatef(xy[0] * scale, xy[1] * scale, 1.4f);
            csr.draw(gl);
            gl.glTranslatef(-xy[0] * scale, -xy[1] * scale, -1.4f);
        }
        
        if(card != null){
            card.draw(gl);
        }

        gl.glScalef(scale, scale, scale);

        for (MiniMarker miniMarker : markers) {
            miniMarker.draw(gl);
        }

        

        gl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);

        gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
        gl.glLoadIdentity();    // reset
        glu.gluPerspective(45.0f, viewport[2] / (float) viewport[3], 0.1f, 500.0f);

        gl.glEnable(GL2.GL_DEPTH_BUFFER);
    }

    public void drawHex(GL2 gl, float px, float py) {
        for (int i = 0; i < 12; i += 2) {
            gl.glVertex3f(hex[i] + px, hex[i + 1] + py, 1);
        }
    }

    public float[] mapToGrid(int x, int y) {
        return new float[]{x * tgx - width, y * th * 2 + (x % 2 == 0 ? -th : 0) - height, 1};
    }

    public float[] getMarkerPosition(int x) {

        return mapToGrid(tiles.get(x).x + 1, tiles.get(x).y);
    }

    public int size() {
        return tiles.size();
    }

    public ProximityGroup getPg() {
        return pg;
    }
    
    public void animateCard(Card c) {
//        System.out.println(c.getType());
        if(c.getType().equals("Death")){
            card = new CardRenderer("Death","Death-front", specialTiles.get(0));
        } else if(c.getType().equals("Tax")){
            card = new CardRenderer("Tax","Tax-front", specialTiles.get(1));
        }
    }
    
    public void clearCard(){
        card = null;
    }
    
    public void setDice(int[] values){
        bowl.roll(values);
    }
}
